Go’s Defer statement
Introduction
Defer statement is used to postpone the execution of following function. The function is called even if the program panics. Let's take a closer look at how to use it.
Basics
For those coming from other languages like for example Python, defer statement is somewhat similar to Python's try/except/finally, where Go's defer is the finally part. Defer postpones execution of function until the surrounding function returns.
In below example we have two prints, but the first one is prefixed with defer statement. It is that print that will be executed when the main function returns.
func main() { defer fmt.Println("World") fmt.Println("Hello") }
The output is the following
Hello World
Any function prefixed with defer will be executed even if the program panics.
func main() { defer fmt.Println("World") panic("Something went wrong") fmt.Println("Hello") }
In the output of the program we can see that "World" has been printed out even though the program paniced"
World panic: Something went wrong goroutine 1 [running]: main.main() /home/michal/tmp_scripts/defer.go:7 +0x95 exit status 2
Order of execution
If there are several defer calls, the functions are called last-in-first-out order. We will call print 3 times with different messages and see what happens.
func main() { defer fmt.Println("Print #1") defer fmt.Println("Print #2") defer fmt.Println("Print #3") }
As seen below, even though the Print #1 was defined first it was called last, and Print #3 was defined last, it executed first.
Print #3 Print #2 Print #1
Deferred anonymous function
A deferred anonymous functions are able to access and modify return parameters of the surrounding function.
func main() { res := deferredFunc() fmt.Println(res) } func deferredFunc() (result string) { defer func() { result = "from deferred function" }() return "Hellow world" }
Contrary to some expectations the output is the string coming from anonymous function instead the "Hello world" string.
from deferred function
Applications
The defer statement as stated above is similar to Python's finally in try/except block. In Go, it is used to perform clean up actions like closing a file or unlocking a mutex. These actions should be performed regardless of program running normally or panicking.
Conlusion
We discovered the behavior that defer statement has on functions it prefixes. We know that deferred function will execute even if program panics. If multiple defer statements are called, the last one will be called first and first one as last. The main functionality of defer statement is to make sure that clean up actions will be executed even in the event of panic.